package com.ndp.fb.walle.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.ndp.fb.walle.config.json.ComplexPropertyPreFilter;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.nio.charset.Charset;

/**
 * Created by hunk.qin on 2016/3/18.
 */
public class FilterFastJsonRestHttpMessageConverter extends AbstractHttpMessageConverter<Object> {

    public final static Charset UTF8     = Charset.forName("UTF-8");

    private Charset             charset  = UTF8;

    private SerializerFeature[] features = new SerializerFeature[0];

    public FilterFastJsonRestHttpMessageConverter(){
        super(new MediaType("application", "json", UTF8),
                new MediaType("text", "plain", UTF8),
                new MediaType("application", "x-www-form-urlencoded", UTF8),
                new MediaType("application", "form-data", UTF8),
                new MediaType("application", "*+json", UTF8));
    }

    private ComplexPropertyPreFilter serializeFilter;

    public ComplexPropertyPreFilter getSerializeFilter() {
        return serializeFilter;
    }

    public void setSerializeFilter(ComplexPropertyPreFilter serializeFilter) {
        this.serializeFilter = serializeFilter;
    }
    @Override
    protected boolean supports(Class<?> clazz) {
        return true;
    }

    public Charset getCharset() {
        return this.charset;
    }

    public void setCharset(Charset charset) {
        this.charset = charset;
    }

    public SerializerFeature[] getFeatures() {
        return features;
    }

    public void setFeatures(SerializerFeature... features) {
        this.features = features;
    }


    @Override
    protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException,
            HttpMessageNotReadableException {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        InputStream in = inputMessage.getBody();

        byte[] buf = new byte[1024];
        for (;;) {
            int len = in.read(buf);
            if (len == -1) {
                break;
            }

            if (len > 0) {
                baos.write(buf, 0, len);
            }
        }

        byte[] bytes = baos.toByteArray();

        if(clazz == String.class){
            return JSON.parseObject(bytes, 0, bytes.length, charset.newDecoder(), clazz);
        }else{
            String str=new String(bytes, 0, bytes.length,charset);
            if(inputMessage.getHeaders().get("content-type").get(0).toString().contains("application/x-www-form-urlencoded")){
                str= URLDecoder.decode(str,charset.toString());
            }
            if(str.startsWith("param=")){
                str=str.substring(6,str.length());
            }
            return JSON.parseObject(str, clazz);
        }

    }

    @Override
    protected void writeInternal(Object obj, HttpOutputMessage outputMessage) throws IOException,
            HttpMessageNotWritableException {
        OutputStream out = outputMessage.getBody();
        System.out.println("FilterFastJsonRestHttpMessageConverter----------start");
        System.out.println(obj.getClass());
        System.out.println("FilterFastJsonRestHttpMessageConverter----------end");
        if(obj instanceof  String||obj instanceof ResponseEntity){
            if(obj instanceof  String){
                out.write(obj.toString().getBytes(getCharset()));
            }else{
                ResponseEntity responseEntity=(ResponseEntity)obj;
                Object body = responseEntity.getBody();
                if(body instanceof  String){
                    out.write(body.toString().getBytes(getCharset()));
                }
            }

        }else{
            if(!(obj instanceof  RestModel)){
                obj=new RestModel(true,"","", obj,"success");
            }
            if (serializeFilter != null) {
                String text = JSON.toJSONString(obj, serializeFilter, getFeatures());
                byte[] bytes = text.getBytes(getCharset());
                out.write(bytes);
            } else {
                String text = JSON.toJSONString(obj, getFeatures());
                byte[] bytes = text.getBytes(getCharset());
                out.write(bytes);
            }
        }

    }
}